package com.rw.tool.util.io.file.serialize;

import com.rw.tool.util.io.file.property.*;
import com.rw.tool.util.io.file.wrapper.FileLambdaQueryWrapper;
import com.rw.tool.util.io.file.wrapper.LambdaGetter;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 序列化字段解析器
 *
 * @param <T> javabean的类型
 */
public class SerializeBeanParser<T> extends IdGetterBeanParser<T, Field> {
    /**
     * 声明一个json的属性解析器
     *
     * @param idListGetter 自定义id属性获取
     */
    public SerializeBeanParser(IdListGetter<Field> idListGetter) {
        super(idListGetter);
    }

    /**
     * 声明一个json的属性解析器，默认使用@FileId注解来标识id属性
     */
    public SerializeBeanParser() {
        super(SerializeBeanParser::getIdList);
    }

    /**
     * 获取类对象里面所有可以被序列化的字段
     *
     * @param tClass 类对象
     * @return 所有字段
     */
    @Override
    public List<Field> getAllField(Class<T> tClass) {
        return getAllFieldByRecursion(tClass);
    }

    /**
     * 根据 fieldList 获取里面的所有ID属性
     */
    protected static List<IdProperty<Field>> getIdList(List<Field> fieldList) {
        List<IdProperty<Field>> idGetterList = new ArrayList<>();
        // 遍历所有属性
        for (Field field : fieldList) {
            FileId fileId = field.getAnnotation(FileId.class);
            // 如果没有注解，则跳过
            if (fileId == null) {
                continue;
            }

            // 构造id属性
            IdProperty<Field> idProperty = new IdProperty<>(fileId.autoIncrement(), field);
            idGetterList.add(idProperty);
        }

        return idGetterList;
    }

    /**
     * 获取类对象里面所有可以被序列化的字段
     *
     * @param tClass 类对象
     * @param <T>    类型
     * @return 所有字段
     */
    protected static <T> List<Field> getAllFieldByRecursion(Class<T> tClass) {
        // 获取所有声明的字段（包括私有字段）
        Field[] fields = tClass.getDeclaredFields();

        // 不需要transient或static的字段
        List<Field> fieldList = Arrays.stream(fields)
                .filter(field -> !Modifier.isTransient(field.getModifiers()))
                .filter(field -> !Modifier.isStatic(field.getModifiers()))
                .peek(field -> field.setAccessible(true))
                .collect(Collectors.toList());

        // 递归获得父类中的字段
        if (tClass.getSuperclass() != null && !tClass.getSuperclass().equals(Object.class)) {
            fieldList.addAll(getAllFieldByRecursion(tClass.getSuperclass()));
        }

        return fieldList;
    }

    /**
     * 解析field的属性，封装为自定义的接口
     *
     * @param field 属性
     * @return 自定义的接口
     */
    protected FileProperty<T> toFileProperty(Field field, boolean autoIncrement) {
        // 获取属性名
        String name = field.getName();
        // 声明属性的访问器
        FieldPropertyVisitor<T> fieldPropertyVisitor = new FieldPropertyVisitor<>(field);

        return new FileProperty<>(name, autoIncrement, fieldPropertyVisitor);
    }

    /**
     * 声明一个根据id过滤的过滤器
     *
     * @param idList          id列表
     * @param autoIncrementId 自增id
     */
    public static <T> SerializeBeanParser<T> ofIdFilter(List<String> idList, List<String> autoIncrementId) {
        return new SerializeBeanParser<>(new FilterIdGetter<>(idList, autoIncrementId, Field::getName));
    }

    /**
     * 声明一个根据id过滤的过滤器
     *
     * @param id            id
     * @param autoIncrement 是否自增
     */
    public static <T> SerializeBeanParser<T> ofIdFilter(String id, boolean autoIncrement) {
        return new SerializeBeanParser<>(new FilterIdGetter<>(id, autoIncrement, Field::getName));
    }

    /**
     * 声明一个根据id过滤的过滤器
     *
     * @param idList id列表
     */
    public static <T> SerializeBeanParser<T> ofIdFilter(List<String> idList) {
        return new SerializeBeanParser<>(new FilterIdGetter<>(idList, Field::getName));
    }


    /**
     * 声明一个根据id过滤的过滤器
     *
     * @param id id
     */
    public static <T> SerializeBeanParser<T> ofIdFilter(String id) {
        return new SerializeBeanParser<>(new FilterIdGetter<>(id, Field::getName));
    }

    /**
     * 声明一个根据id过滤的过滤器
     *
     * @param lambdaIdList          id列表
     * @param lambdaAutoIncrementId 自增id
     */
    public static <T> SerializeBeanParser<T> ofLambdaIdFilter(List<LambdaGetter<T>> lambdaIdList,
                                                              List<LambdaGetter<T>> lambdaAutoIncrementId) {
        List<String> idList = lambdaIdList.stream()
                .map(FileLambdaQueryWrapper::parseLambdaName)
                .collect(Collectors.toList());

        List<String> autoIncrementId = lambdaAutoIncrementId.stream()
                .map(FileLambdaQueryWrapper::parseLambdaName)
                .collect(Collectors.toList());

        return ofIdFilter(idList, autoIncrementId);
    }

    /**
     * 声明一个根据id过滤的过滤器
     *
     * @param lambdaId      id
     * @param autoIncrement 是否自增
     */
    public static <T> SerializeBeanParser<T> ofLambdaIdFilter(LambdaGetter<T> lambdaId, boolean autoIncrement) {
        return ofIdFilter(FileLambdaQueryWrapper.parseLambdaName(lambdaId), autoIncrement);
    }

    /**
     * 声明一个根据id过滤的过滤器
     *
     * @param lambdaIdList id列表
     */
    public static <T> SerializeBeanParser<T> ofLambdaIdFilter(List<LambdaGetter<T>> lambdaIdList) {
        List<String> idList = lambdaIdList.stream()
                .map(FileLambdaQueryWrapper::parseLambdaName)
                .collect(Collectors.toList());

        return ofIdFilter(idList);
    }


    /**
     * 声明一个根据id过滤的过滤器
     *
     * @param lambdaId id
     */
    public static <T> SerializeBeanParser<T> ofLambdaIdFilter(LambdaGetter<T> lambdaId) {
        return ofIdFilter(FileLambdaQueryWrapper.parseLambdaName(lambdaId));
    }
}
